﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using YoutubeExtractor;

namespace FeedBack {
    class YouTubeDownloader : IDownloader {

        private string path;

        public void Download(Story story) {
            // Our test youtube link
            string link = (story.Source ?? story.Link).ToString();

            /*
             * Get the available video formats.
             * We'll work with them in the video and audio download examples.
             */
            IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link, false);

            if (videoInfos == null) {
                OnComplete(story, false);
            }
            else {
                DownloadVideo(videoInfos, story);
            }
        }

        private void DownloadVideo(IEnumerable<VideoInfo> videoInfos, Story story) {
            /*
             * Select the first .mp4 video with 360p resolution
             */
            var infos = videoInfos
                .Where(info => info.VideoType == VideoType.Mp4)
                .Where(info => info.Resolution <= 720)
                .OrderByDescending(info => info.Resolution);
            VideoInfo video = infos.First();

            /*
             * If the video has a decrypted signature, decipher it
             */
            if (video.RequiresDecryption) {
                DownloadUrlResolver.DecryptDownloadUrl(video);
            }

            /*
             * Create the video downloader.
             * The first argument is the video to download.
             * The second argument is the path to save the video file.
             */
            string dir = Configuration.InProgressFolder;
            if (!Directory.Exists(dir)) {
                Directory.CreateDirectory(dir);
            }
            path = Path.Combine(dir,
                video.Title.RemoveIllegalPathCharacters() + video.VideoExtension);

            var videoDownloader = new VideoDownloader(video, path);
            var fileSize = 0L;
            var x = 0;
            for (; File.Exists(path) && x < 10; ) {
                FileStream stream = null;
                try {
                    stream = File.OpenRead(path);
                    if (fileSize == stream.Length){
                        x++;
                    } else {
                        fileSize = stream.Length;
                    }
                } catch {
                    if (stream != null){
                        stream.Close();
                    }
                }
                Thread.Sleep(10000);
            }

            // Register the ProgressChanged event and print the current progress
            videoDownloader.DownloadFinished += (a, b) => {
                OnComplete(story, true);
            };

            /*
             * Execute the video downloader.
             * For GUI applications note, that this method runs synchronously.
             */
            videoDownloader.Execute();
        }

        private void OnComplete(Story story, bool success) {
            if (Completed != null) {
                Completed(this, new StoryDownloadedEventArgs { Filename = path, Story = story, Success = success });
            }
        }

        public event EventHandler<StoryDownloadedEventArgs> Completed;


        public string CandidateFileName(Story story) {
            // Our test youtube link
            string link = (story.Source ?? story.Link).ToString();

            /*
             * Get the available video formats.
             * We'll work with them in the video and audio download examples.
             */
            IEnumerable<VideoInfo> videoInfos = DownloadUrlResolver.GetDownloadUrls(link, false);
            if (videoInfos == null) {
                return null;
            }
            /*
             * Select the first .mp4 video with 360p resolution
             */
            VideoInfo video = videoInfos
                .OrderByDescending(info => info.Resolution)
                .First(info => info.VideoType == VideoType.Mp4);

            /*
             * If the video has a decrypted signature, decipher it
             */
            if (video.RequiresDecryption) {
                DownloadUrlResolver.DecryptDownloadUrl(video);
            }

            return video.Title.RemoveIllegalPathCharacters() + video.VideoExtension;
        }

        public void PostProcess(string storyDirectory, Story story) {
            // Do nothing
        }
    }
}
